package com.blackrock.das.service;

import static java.lang.String.format;

import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Random;

import javax.annotation.PostConstruct;

import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.datastax.driver.core.Session;

// TODO: Auto-generated Javadoc
/**
 * The Class DataInitialiser.
 */
@Component
public class DataInitialiser {

    /** The Constant LOGGER. */
    private static final Logger LOGGER = LoggerFactory.getLogger(DataInitialiser.class);

    /** The Constant CQL_INSERT_TIME_SERIES. */
    private static final String CQL_INSERT_TIME_SERIES = "INSERT INTO PortfolioTimeSeries (isin, date, fundReturn, benchReturn, AUM, sharesInIssue, NAV, weekly, monthly) VALUES ('%s', %d,  %f, %f,  %f,  %f,  %f, %s, %s);";

    /** The Constant CQL_INSERT_STATIC_DATA. */
    private static final String CQL_INSERT_STATIC_DATA = "INSERT INTO PortfolioStaticData (isin, ticker, fundName, benchmarkName, inceptionDate) VALUES ('%s', '%s',  '%s', '%s', %d);";

    /** The Constant NODE. */
    private static final String NODE = "localhost";

    /** The cassandra service. */
    @Autowired
    private CassandraService cassandraService;

    /**
     * Inits the.
     */
    @PostConstruct
    public void init() {
        LOGGER.debug("DB init");
        cassandraService.connect(NODE);

        Session session = cassandraService.getSession();
        createTables(session);

    }

    /**
     * Regenerate key space.
     */
    public void regenerateKeySpace() {
        LOGGER.info("Regenerating the key space");

        Session session = cassandraService.getSession();
        session.execute("DROP KEYSPACE IF EXISTS hackathon;");
        createTables(session);

    }

    /**
     * Creates the tables.
     *
     * @param session the session
     */
    private void createTables(Session session) {
        LOGGER.debug("Trying to create key space if not existent");

        session.execute("CREATE KEYSPACE IF NOT EXISTS hackathon WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};");
        session.execute("USE hackathon;");
        session.execute("CREATE TABLE IF NOT EXISTS PortfolioTimeSeries (isin text, date timestamp, fundReturn decimal, benchReturn decimal, AUM decimal, sharesInIssue decimal, NAV decimal, monthly boolean, weekly boolean, PRIMARY KEY (isin, date));");
        session.execute("CREATE TABLE IF NOT EXISTS PortfolioStaticData (isin text, ticker text, fundName text, benchmarkName text, inceptionDate timestamp, PRIMARY KEY (isin));");
        session.execute("CREATE INDEX IF NOT EXISTS ON PortfolioTimeSeries (monthly);");
        session.execute("CREATE INDEX IF NOT EXISTS ON PortfolioTimeSeries (weekly);");
    }

    /**
     * Insert mock data.
     */
    public void generateMockData() {
        LOGGER.debug("Writting mock data into the database");

        String insertStmt;
        Session session = cassandraService.getSession();
        DateTime dateTime = new DateTime();

        Map<String, Map<String, Object>> staticDataMap = new HashMap<String, Map<String, Object>>();

        staticDataMap.put(
                "UK342344432",
                createMockStaticData("UK342344432", "XAB", "iShares Fund XAB", "iShares Benchmark XAB", new DateTime(2000, 01, 01, 0, 0, 0,
                        0).toDate().getTime()));

        staticDataMap.put(
                "IE32423432423",
                createMockStaticData("IE32423432423", "XBB", "iShares Fund XBB", "iShares Benchmark XBB", new DateTime(2000, 01, 01, 0, 0,
                        0, 0).toDate().getTime()));

        staticDataMap.put(
                "DE4535435345",
                createMockStaticData("DE4535435345", "XCC", "iShares Fund XCC", "iShares Benchmark XCC", new DateTime(2000, 01, 01, 0, 0,
                        0, 0).toDate().getTime()));

        for (String isin : staticDataMap.keySet()) {
            Map<String, Object> staticData = staticDataMap.get(isin);

            insertStmt = format(CQL_INSERT_STATIC_DATA, isin, staticData.get("ticker"), staticData.get("fundName"),
                    staticData.get("benchmarkName"), staticData.get("inceptionDate"));

            LOGGER.debug(insertStmt);
            session.execute(insertStmt);

            for (int i = 0; i < 30; i++) {
                DateTime currentDate = dateTime.minusDays(i);

                Date asOfDate = currentDate.toDate();
                Random random = new Random();
                Double nav = random.nextDouble();
                Double fundRet = random.nextDouble();
                Double bechRet = random.nextDouble();
                Double aum = random.nextDouble();
                Double sharesInIssue = random.nextDouble();

                boolean weekly = (currentDate.getDayOfWeek() == DateTimeConstants.FRIDAY);
                boolean monthly = currentDate.dayOfMonth().withMaximumValue().compareTo(currentDate) == 0;

                insertStmt = format(new Locale("en", "GB"), CQL_INSERT_TIME_SERIES, isin, asOfDate.getTime(), fundRet, bechRet, aum,
                        sharesInIssue, nav, weekly, monthly);

                LOGGER.debug(insertStmt);
                session.execute(insertStmt);
            }
        }
    }

    /**
     * Creates the mock static data.
     *
     * @param isin the isin
     * @param ticker the ticker
     * @param fundName the fund name
     * @param benchmarkName the bench mark name
     * @param inceptionDate the inception date
     * @return the map
     */
    private Map<String, Object> createMockStaticData(String isin, String ticker, String fundName, String benchmarkName, Long inceptionDate) {
        Map<String, Object> staticData = new HashMap<String, Object>();

        staticData.put("isin", isin);
        staticData.put("ticker", ticker);
        staticData.put("fundName", fundName);
        staticData.put("benchmarkName", benchmarkName);
        staticData.put("inceptionDate", inceptionDate);

        return staticData;
    }

}
